<?php

declare(strict_types=1);

namespace app\common\listener;

use app\common\exception\BaseException;
use JsonException;
use think\Container;
use think\facade\Log;
use think\swoole\Websocket;
use \think\facade\Db;
use Swoole\Timer;

class CompanyScreen
{
    protected object $websocket;
    protected array  $tickId;

    protected int $company_id;

    public function __construct(Container  $container)
    {
        $this->websocket = $container->make(Websocket::class);
    }


    /**
     * @param $event
     * @throws BaseException
     * @throws JsonException
     */
    public function handle($event): void
    {
        $param = json_decode($event->data, true);
        $this->company_id = (int)$param['company_id'];
        //  合伙人地图位置
        $this->mapLocation();
        // 出入库数据
        $this->warehouseData($event,  $param);
        // 仓内概况
        $this->warehouseOverview($event, $param);
        // 销售数据
        $this->salesList($event, $param);
        // 经营数据
        $this->operateData($event, $param);
        // 仓库商品预警
        $this->whGoodsWarring($event, $param);
        //        // 门店订单
        $this->storeOrder($event, $param);
    }

    /**
     * 合伙人地图位置 要进行优化
     */
    public function mapLocation(): void
    {
        $company = Db::name('company')
                     ->where('id',$this->company_id)
                     ->field('id,name,short_name,area_id,address,lng,lat')
                     ->find();

        $company['title'] =$company['short_name']. '商业体系运营管理平台';

        $store   =  Db::name('store')->where([['company_id', '=', $this->company_id], ['status', '=', 1]])
                      ->field('id,name,lon,lat')
                      ->select();

        $wh      =  Db::name('company_warehouse')
                      ->where('company_id',$this->company_id)
                      ->where('status', 1)
                      ->field('id,name,lon,lat')
                      ->select();

        $this->websocket->to($this->websocket->getSender())->emit('map', compact('company', 'store', 'wh'));
    }
    /**
     * 出入库数据
     */
    public function warehouseData(): void
    {
        // 初始化数据库模型
        $reportGoodsOutModel = Db::name('report_goods_out');
        $dealerOrderModel = Db::name('dealer_order');
        $companyOrderModel = Db::name('company_order');
        $transferOrderModel = Db::name('company_transfer_order');
        $storeModel = Db::name('store');
        $driverModel = Db::name('driver');
        $dealerOrderDetailModel = Db::name('dealer_order_detail');
        $companyOrderDetailModel = Db::name('company_order_detail');
        $transferOrderDetailModel = Db::name('company_transfer_order_detail');
        $dealerSpecModel = Db::name('dealer_goods_spec');

        // 初始化统计变量
        $totalOutNum = 0;
        $totalOutMoney = 0;
        $totalInNum = 0;
        $totalInMoney = 0;
        $todayInOrders = 0;
        $todayOutOrders = 0;
        $totalSales = 0;

        // 1. 总出库数量和金额
        $reportGoodsOutData = $reportGoodsOutModel->field('big_unit_out_num, middle_unit_out_num, small_unit_out_num, big_unit_out_value, middle_unit_out_value, small_unit_out_value')
                                                  ->select();
        foreach ($reportGoodsOutData as $item) {
            $totalOutNum += $item['big_unit_out_num'] + $item['middle_unit_out_num'] + $item['small_unit_out_num'];
            $totalOutMoney += $item['big_unit_out_value'] + $item['middle_unit_out_value'] + $item['small_unit_out_value'];
        }
        $totalOutMoney = sprintf("%.2f", $totalOutMoney);

        // 2. 总入库数量和金额
        // 2.1 采购入库
        $updateAt = date('Y-m-d'); // 今日时间
        $dealerOrderCount = $dealerOrderModel->where(['order_status' => 3])
                                             ->whereTime('create_time', 'today')
                                             ->count();
        $dealerOrderData = $dealerOrderModel->where(['order_status' => 3])
                                            ->select()
                                            ->toArray();

        foreach ($dealerOrderData as $order) {
            $orderDetails = $dealerOrderDetailModel->where('dealer_order_id', $order['id'])->withTrashed()->select()->toArray();
            foreach ($orderDetails as $detail) {
                $totalInNum += $detail['num'];
                $totalInMoney += $detail['purchase_total_price'];
            }
        }

        // 2.2 销退入库
        $companyOrderCount = $companyOrderModel->where(['out_status' => 2])
                                               ->whereTime('create_time', 'today')
                                               ->count();
        $companyOrderData = $companyOrderModel->where(['out_status' => 2])
                                              ->select()
                                              ->toArray();

        foreach ($companyOrderData as $order) {
            $orderDetails = $companyOrderDetailModel->where('company_order_id', $order['id'])->select()->toArray();
            foreach ($orderDetails as $detail) {
                $totalInNum += $detail['num'];
                $totalInMoney += $detail['total_price'];
            }
        }

        // 2.3 调拨入库单
        $transferOrderCount = $transferOrderModel->where('company_id', $this->company_id)
                                                 ->where('check_status', 2)
                                                 ->where('transfer_type', 2)
                                                 ->whereTime('create_time', 'today')
                                                 ->count();
        $transferOrderData = $transferOrderModel->where('company_id', $this->company_id)
                                                ->where('check_status', 2)
                                                ->where('transfer_type', 2)
                                                ->select()
                                                ->toArray();

        foreach ($transferOrderData as $transfer) {
            $transferDetails = $transferOrderDetailModel->where('t_oid', $transfer['id'])->select()->toArray();
            foreach ($transferDetails as $detail) {
                $totalInNum += $detail['transfer_num'];
                $spec = $dealerSpecModel->where('id', $detail['dealer_goods_spec_id'])->find();
                $totalInMoney += $detail['transfer_num'] * ($spec['purchase_price'] ?? 0);
            }
        }

        // 3. 今日入库订单量
        $todayInOrders = $dealerOrderCount + $companyOrderCount + $transferOrderCount;

        // 4. 今日出库订单量
        $todayOutOrders = $reportGoodsOutModel->whereTime('time', 'today')->count();

        // 5. 总销售金额
        $totalSales = $companyOrderModel->where(['order_type' => 1, 'order_status' => 2])
                                        ->sum('order_amount');

        // 6. 总门店数
        $totalStore = $storeModel->where('company_id', $this->company_id)
                                 ->where('status', 1)
                                 ->where('delete_time', null)
                                 ->count();

        // 7. 总车辆数
        $totalCar = $driverModel->where('company_id', $this->company_id)->count();

        // 组装结果数据
        $warehouseData = [
                'total_out'       => $totalOutNum,
                'total_out_money' => $totalOutMoney,
                'total_in'        => $totalInNum,
                'total_in_money'  => sprintf("%.2f", $totalInMoney),
                'today_in'        => $todayInOrders,
                'today_out'       => $todayOutOrders,
                'total_sales'     => $totalSales,
                'total_store'     => $totalStore,
                'total_car'       => $totalCar,
        ];

        // 推送数据
        $this->websocket->to($this->websocket->getSender())->emit('warehouse', $warehouseData);
    }

    /**
     * 仓库概览
     */
    public function warehouseOverview($frame, mixed $arr): void
    {

        $warehouse_overview = Db::table('vk_goods_cate')->where('status', 1)
                                ->where('pid', 0)
                                ->field('id,name')
                                ->select()
                                ->toArray();

        foreach ($warehouse_overview as $k => &$item) {

            $cate_ids = Db::table('vk_goods_cate')
                          ->where('pid', $item['id'])
                          ->column('id');

            $order    =  Db::table('vk_dealer_order_detail');
            $order_detail_data =  $order->where('goods_cate_id', 'in', $cate_ids)->field('real_price,num')->select()->toArray();

            $amount = 0;
            foreach ($order_detail_data as $k => $v) {
                $amount += $v['real_price'] * $v['num'];
            }

            $item['amount'] = $amount;
        }

        $amounts = array_column($warehouse_overview, 'amount');
        array_multisort($amounts, SORT_DESC, $warehouse_overview);

        $data = array_slice($warehouse_overview, 0, 7);

        $qita_arr = array_slice($warehouse_overview,  8);

        array_push($data, ['name' => '其他', 'amount' => array_sum(array_column($qita_arr, 'amount'))]);

        $total_amount = array_sum(array_column($warehouse_overview, 'amount'));
        $this->websocket->to($this->websocket->getSender())->emit('warehouse_overview',  compact('data', 'total_amount'));
    }

    /**
     * 销售列表
     */
    public function salesList($frame, mixed $arr): void
    {
        $def_num     = 7;
        $list        = [];
        $create_time = [];
        if (isset($arr['create_time']) && !empty($arr['create_time'])) $create_time = $arr['create_time'];

        if (isset($create_time[0]) && isset($create_time[1])) {
            $time = $create_time[1];
            $num  = $this->difTime(strtotime($create_time[1]), strtotime($create_time[0]));
        } else {
            $time = date('Y-m-d');
            $num  = $def_num;
        }
        $company_order_model =  Db::table('vk_company_order');

        for ($i = 0; $i < $num + 1; $i++) {
            $date           = date('Y-m-d', strtotime('-' . $i . ' day', strtotime($time)));
            $start          = strtotime($date);
            $end            = strtotime($date) + 86400;
            $arr['date']    = $date;
            $order_data = $company_order_model->whereBetween('create_time', [$start, $end])->where([['order_status', '=', 2], ['order_type', '=', 1]])
                                              ->select()->toArray();
            $amount = 0;
            foreach ($order_data as $k => $v) {
                $company_order_detail =  Db::table('vk_company_order_detail');
                $total_price_arr =    $company_order_detail->where([['company_order_pid', '=', $v['id']]])->field('total_price')->select()->toArray();
                $amount         += array_sum($total_price_arr);
            }
            $arr['amount'] = $amount;
            $list[]        = $arr;
        }

        $this->websocket->to($this->websocket->getSender())->emit('sales_list', $list);
    }

    /**
     * 经营数据
     */
    public function operateData(): void
    {
        // 获取当前公司的基本信息
        $companyList = Db::table('vk_company')
                         ->where('id', $this->company_id)
                         ->field('id, name')
                         ->select()
                         ->toArray();

        // 合并统计查询
        $stats = $this->getCompanyStats($this->company_id);

        // 拼接统计数据到公司列表中
        foreach ($companyList as &$company) {
            $company['purchase_count'] = $stats['purchase_count'];
            $company['wh_count'] = $stats['wh_count'];
            $company['wh_area_count'] = $stats['wh_area_count'];
            $company['wh_position_count'] = $stats['wh_position_count'];
            $company['car_count'] = $stats['car_count'];
            $company['goods_count'] = $stats['goods_count'];
            $company['sales_amount'] = $stats['sales_amount'];
        }

        $this->websocket->to($this->websocket->getSender())->emit('operate_data', $companyList);
    }

    /**
     * 获取公司相关统计数据
     * @param int $companyId 公司ID
     * @return array 统计数据
     */
    public function getCompanyStats($companyId): array
    {
        $stats = [];

        // 采购数量
        $stats['purchase_count'] = Db::name('company_order')
                                     ->where('company_id', $companyId)
                                     ->where('order_status', 2)
                                     ->count() ?? 0;

        // 仓库数量
        $stats['wh_count'] = Db::name('company_warehouse')
                               ->where('company_id', $companyId)
                               ->count() ?? 0;


        // 库区数量
        $stats['wh_area_count'] = Db::name('company_warehouse_area')
                                    ->where('company_id', $companyId)
                                    ->count() ?? 0;

        // 库位数量
        $stats['wh_position_count'] = Db::name('company_warehouse_location')
                                        ->where('company_id', $companyId)
                                        ->count() ?? 0;

        // 车辆数量
        $stats['car_count'] = Db::name('driver')
                                ->where('company_id', $companyId)
                                ->count() ?? 0;

        // 在仓商品数量
        // $goodsCount = Db::name('dealer_goods_spec')
        //                 ->alias('dgs')
        //                 ->join(['dealer_goods' => 'dg'], 'dgs.dealer_goods_id = dg.id')
        //                 ->where('dg.company_id', $companyId)
        //                 ->sum('dgs.sales_stock') ?? 0;  sales_stock

        $goodsCount = Db::name('dealer_goods')->where('company_id',$companyId)->sum('warehouse_stock');

        $stats['goods_count'] = $goodsCount ?: 0;

        // 总销数量
        $salesAmount =  Db::name('dealer_goods')->where('company_id',$companyId)->sum('sales_stock');

        $stats['sales_amount'] = $salesAmount ?: 0;

        return $stats;
    }



    // 仓库商品预警 TODO 未完成逻辑
    public function whGoodsWarring($frame, mixed $arr)
    {
        $def_num = 7;
        $list    = [];
        $time    = strtotime(date('Y-m-d')); // 获取当前时间的时间戳
        $sql     =  Db::table('vk_dealer_goods');

        // 当前预警数量
        $now_expired      = 0;
        /*$now_near_expired = $sql->where('expire_time', '<=', $time)
            ->where('expire_time', '>', $time - (60 * 24 * 3600))
            ->count();*/
        $now_near_expired  = 7;
        for ($i = 0; $i <= $def_num; $i++) {
            $date        = date('Y-m-d', strtotime('-' . $i . ' day', $time));
            $expire_time = $time - (60 * 24 * 3600); // 60天前的日期时间戳
            /*$num         = $sql->where('expire_time', '>=', $expire_time)
                ->where('expire_time', '<=', $time + (86400 * ($i + 1))) // 当前时间加上($i + 1)天
                ->count();*/
            $num = rand(1, 1000);
            $arr['date'] = $date;
            $arr['num']  = $num; // 这里假设我们总是需要真实数据
            $list[]      = $arr;
        }


        $this->websocket->to($this->websocket->getSender())->emit('wh_goods_warring',  compact('now_expired', 'now_near_expired', 'list'));
    }

    /**
     * 订单列表 TODO 数据应该不准确
     */
    public function storeOrder($frame, mixed $arr): void
    {
        // 获取订单列表
        $storeOrder = Db::name('company_order')->where([['order_status', '=', 2]]);

        if (isset($arr['company_id'])) $storeOrder->where('company_id', $arr['company_id']);

        if (isset($arr['create_time']) && !empty($arr['create_time'])) $create_time = $arr['create_time'];

        if (isset($create_time[0]) && isset($create_time[1])) {
            $create_time[0] = strtotime($create_time[0]);
            $create_time[1] = strtotime($create_time[1]);
            $storeOrder->whereBetween('create_time', $create_time);
        }

        $list = $storeOrder->field('store_id,company_id,order_no,create_time')
                           ->order('id', 'desc')
                           ->select()->toArray();

        foreach ($list as $k => &$item) {
            $item['create_time'] = date('Y-m-d H:i:s', $item['create_time']);
            $item['company_name'] = Db::table('vk_company')->where('id', $item['company_id'])->withTrashed()->field('name')
                                      ->value('name');
            $item['store_name']   = Db::table('vk_store')->where('id', $item['store_id'])->withTrashed()->field('name')
                                      ->value('name');
        }

        $this->websocket->to($this->websocket->getSender())->emit('store_order',  $list);
        // 定时推送
        $this->tickId[$this->websocket->getSender()] = Timer::tick(60000, function () use ($frame, $arr) {
            // 获取订单列表
            $storeOrder =  Db::table('vk_company_order')->where('order_status', 2);

            if (isset($arr['company_id'])) $storeOrder->where('company_id', $arr['company_id']);

            if (isset($arr['create_time']) && !empty($arr['create_time'])) $create_time = $arr['create_time'];

            if (isset($create_time[0]) && isset($create_time[1])) {
                $create_time[0] = strtotime($create_time[0]);
                $create_time[1] = strtotime($create_time[1]);
                $storeOrder->whereBetween('create_time', $create_time);
            }

            $list = $storeOrder->field('store_id,company_id,order_no,create_time')
                               ->order('id', 'desc')
                               ->select();
            foreach ($list as $k => &$item) {
                $item['create_time'] = date('Y-m-d H:i:s', $item['create_time']);
                $item['company_name'] = Db::table('vk_company')->where('id', $item['company_id'])->value('name');
                $item['store_name']   == Db::table('vk_store')->where('id', $item['store_id'])->value('name');
            }


            $this->websocket->to($this->websocket->getSender())->emit('store_order', $list);
        });
    }



    /**
     * 清除定时器
     */
    public function delTickId($fd): void
    {
        if (isset($this->tickId[$fd])) {
            Timer::clear($this->tickId[$fd]);
        }
    }

    /**
     * 获取两个时间差(用于商品过期预警)
     */
    function difTime($created_time, int $start_time = 0)
    {
        if (0 == $created_time) {
            return 0;
        }
        $createdTime = new \DateTime(date("Ymd His", $created_time));
        // 获取当前时间
        if (0 == $start_time)   $now = new \DateTime();
        if (0 != $start_time)   $now = new \DateTime(date("Ymd His", $start_time));

        $diff = $now->diff($createdTime);

        return abs($diff->days);
    }
}
